#ifndef INCLUDE_FS_H_
#define INCLUDE_FS_H_

#include <type.h>
#include <os/sched.h>
#include <sbi.h>
//the start block of fs
//offset 512M = 2^20 block
//9 inode per sector ->512/56 = 9
//restrict 1 dentry only use 1 sector
//at most support 4-level dir
//path length at most 100
#define FS_BLOCK_NUM ((uint64_t)1<<20)
#define FS_MAGIC 0x123456789abcdef0
#define FS_INODE_NUM 4096
#define OP_SUCCESS 1

#define FS_START_ADDR (1<<15)
#define SUPERBLOCK_SIZE 1
#define BLOCKMAP_SIZE 16
#define INODEMAP_SIZE 1
#define INODETABLE_SIZE 112 //1024*14*4/512

typedef struct superblock
{
	const uint64_t magic;
	uint64_t used_size;//byte
	const uint64_t Inode_Num;
	const uint64_t DataBlock_Num;
	uintptr_t InodeMap_Entry;
	uintptr_t BlockMap_Entry;
	uintptr_t InodeTable_Entry;//num of block
	uintptr_t DataBlock_Entry;//num of block
} superblock_t;

typedef struct inode
{
	uint32_t mode;//file or folder
	uint32_t file_size;//byte
	//uint32_t link_num;
	uint32_t soft_ln;
	uint32_t DirctIndex[9];
	uint32_t FstIndex;
	//uint32_t SndIndex;
	//TODO:index
} inode_t;

typedef struct dentry
{
	char filename[16];
	int  ino;//inode number
	int  used;
} dentry_t;


/*
* The first inode in InodeTable is reserved for root directory
*
*/
void do_touch(char *file_name);


int do_fopen(const char *file_name, int mode);
int do_fwrite(int fd ,char *buffer, int length);
int do_fread(int fd, char *buffer, int length);
int do_fclose(int fd);
void do_cat(char *file_name);
int do_mkfs();
int do_fs_show();
int do_mkdir(char * dir_name,int current_inode_index);
int do_rmdir(char * dir_name,int current_inode_index);
int alloc_inode(int map_entry);
int free_inode(int index);
int alloc_data_block(int map_entry);
int free_data_block(int index);
void do_show_dir(int cur,int argc,char *argv[]);
int do_change_dir(char *dir_name,int path[],int argc,char *argv[]);
void do_rmfs();
int do_link(int argc,char *argv[]);
#endif